package cn.changeforyou.analyzer.javaparse;

import cn.changeforyou.utils.FileDirectoryUtils;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.PackageDeclaration;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @author zhyu
 */
@Slf4j
public class ProjectUtils {
	
	static Map<String, File> parentFileMap = new HashedMap();

	/**
	 * 根据maven项目地址查找整个maven项目中的文件， 如果没有就去试图查找父项目
	 *
	 * @param targetName
	 * @param
	 * @return
	 */
	public static File findFileInMavenProject(String targetName, String projectPath) {
		if (parentFileMap.containsKey(projectPath)) {
			if (log.isDebugEnabled()) {
				log.debug("发现项目地址有缓存, 使用缓存");
			}
			File parentProjectPath = parentFileMap.get(projectPath);
			return FileDirectoryUtils.searchFileInFile(targetName, parentProjectPath);
		}
		File projectFile = new File(projectPath);
		File targetFile = FileDirectoryUtils.searchFileInFile(targetName, projectFile);
		if (null == targetFile) {
			File sonPom = FileDirectoryUtils.searchFileInFile("pom.xml", projectFile);
			if (null == sonPom) {
				log.error("maven 项目的pom文件没有找到");
				return null;
			}
			FileInputStream fisSon = null;
			FileInputStream fisParent = null;
			try {
				fisSon = new FileInputStream(sonPom);
				Model sunModel = new MavenXpp3Reader().read(fisSon);
				Parent parent = sunModel.getParent();
				if (null == parent) {
					log.error("项目没有该文件， 项目也没有父项目");
				}
				String artifactId = parent.getArtifactId();
				String groupId = parent.getGroupId();
				File parentPom = FileDirectoryUtils.searchFileUponFile("pom.xml", projectFile);
				if (null == parentPom) {
					log.error("maven 项目的放置挺不合常理， 在maven子项目的上层没有找到maven父项目的pom文件");
					return null;
				}
				fisParent = new FileInputStream(parentPom);
				Model parentModel = new MavenXpp3Reader().read(fisParent);
				if (groupId.equals(parentModel.getGroupId()) && artifactId.equals(parentModel.getArtifactId())) {
					log.warn("发现项目是多maven项目, 项目地址中没有目标文件, 开始在父项目地址中寻找目标文件");
					File parentProjectPath = parentPom.getParentFile();
					parentFileMap.put(projectPath, parentProjectPath);
					return FileDirectoryUtils.searchFileInFile(targetName, parentProjectPath);
				} else {
					log.error("找到上层的一个pom文件， 但是对比了信息不对,  art1:{}, gro1:{}, art2:{}, gro2:{}", artifactId, groupId, parentModel.getArtifactId(), parentModel.getGroupId());
				}
			} catch (FileNotFoundException e) {
				log.error("error", e);
			} catch (XmlPullParserException e) {
				log.error("error", e);
			} catch (IOException e) {
				log.error("error", e);
			}
		}
		return null;
	}
	
	/***
	 * 根据项目和类型去获取该类的包名
	 * @param projectPath
	 * @param className
	 * @return
	 */
	public static String findClassPackage(String projectPath, String className) {
		String targetName = className + ".java";
		File file = new File(projectPath);
		if (file.exists() && file.isDirectory()) {
			File target = FileDirectoryUtils.searchFileInFile(targetName, file);
			if (null == target) {
				throw new IllegalArgumentException("实体类[" + targetName + "]没有找到");
			}
			CompilationUnit compilationUnit = JavaParseUtils.parseFileAsCompilationUnit(target);
			PackageDeclaration packageDeclaration = compilationUnit.getPackageDeclaration().get();
			return packageDeclaration.getName().toString();
		}
		return null;
	}
	
	/**
	 * 根据一个文件地址获取该地址的java包名
	 *
	 * @param servicePath
	 * @return
	 */
	public static String getDirectoryPackageNameByMavenDefaultSetting(String servicePath) {
		File nearestPom = FileDirectoryUtils.searchFileUponFile("pom.xml", new File(servicePath));
		String pomAbsolutePath = nearestPom.getAbsolutePath();
		String substring = pomAbsolutePath.substring(0, pomAbsolutePath.length() - "pom.xml".length());
		String srcBasePath = substring + "src\\main\\java";
		String endPath = servicePath.substring(servicePath.indexOf(srcBasePath) + srcBasePath.length() + 1);
		String interface_service_package = endPath.replaceAll("\\\\", ".");
		return interface_service_package;
	}
	
}
